package com.sun.enhanceelasticsearch.controller;

import com.alibaba.fastjson.JSON;
import com.sun.enhanceelasticsearch.model.Item;
import com.sun.enhanceelasticsearch.model.UserInfo;
import org.apache.commons.io.FileUtils;
import org.elasticsearch.index.query.MatchPhrasePrefixQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.HighlightQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RestController
public class ElasticSearchController {

    @Autowired
    private ElasticsearchRestTemplate restTemplate;

    /**
     * 按照时间分区排序
     * @return
     */
    @GetMapping("/time")
    public List<UserInfo> selectByTimeFromTo(){
        String begin = "1994-05-12 00:00:00";
        String end = "2023-02-15 00:00:00";
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchAllQuery())
                .withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
                .withFilter(QueryBuilders.rangeQuery("createTime").timeZone("+08:00").format("yyyy-MM-dd HH:mm:ss").gt(begin).lt(end))
                .withQuery(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("phone","13688669854")))
                .withPageable(PageRequest.of(0,5))
                .build();
      return  restTemplate.search(searchQuery,UserInfo.class).get().map(SearchHit::getContent).collect(Collectors.toList());
    }

    /**
     * 高亮显示
     * @return
     */
    @GetMapping("/high")
    public List<UserInfo> highLight() {
        ArrayList<UserInfo> itemVOS = new ArrayList<>();
        MatchPhrasePrefixQueryBuilder prefixQueryBuilder = QueryBuilders.matchPhrasePrefixQuery("nickName", "user");
        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("nickName");
        highlightBuilder.requireFieldMatch(false);//多个高亮关闭
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");

        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withQuery(prefixQueryBuilder)
                .build();
        query.setHighlightQuery(new HighlightQuery(highlightBuilder));

        SearchHits<UserInfo> search  = restTemplate.search(query, UserInfo.class);

        for (SearchHit<UserInfo> searchHit : search) {
            UserInfo content = searchHit.getContent();
            //将高亮的字段取出来
            List<String> requestBody = searchHit.getHighlightField("nickName");
            String highText = "";
            for (String s : requestBody) {
                highText = s;
            }
            //重新对字段赋值
            content.setRequestBody(highText);
            itemVOS.add(content);
        }
        return itemVOS;

    }


    /**
     * 分页查询 + 排序操作
     * @return
     */
    @GetMapping("/find")
    public List<UserInfo> findDataByCondition() {
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchPhrasePrefixQuery("nickName", "user"))
                .withPageable(PageRequest.of(0, 10))
                //按照id排序
                .withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC))
                .build();
        return restTemplate.search(searchQuery, UserInfo.class).get().map(SearchHit::getContent).collect(Collectors.toList());
    }

    /**
     * 向索引中追加数据
     */
    @GetMapping("/add")
    public void addData() throws IOException {
        File file = ResourceUtils.getFile("classpath:SysUser.json");
        String json = FileUtils.readFileToString(file, "UTF-8");
        List<UserInfo> userList = JSON.parseArray(json, UserInfo.class);
        //向ES追加数据
        userList.forEach(x -> restTemplate.save(x));
    }


    /**
     * 创建索引
     *
     * @return
     */
    @GetMapping("/index")
    public boolean createIndex() {
        //查询索引是否存在
        boolean flag = restTemplate.indexOps(IndexCoordinates.of("sys_user")).exists();
        if (flag) {
            //存在就删掉
            restTemplate.indexOps(IndexCoordinates.of("sys_user")).delete();
            //在创建新的索引
            boolean b = restTemplate.indexOps(UserInfo.class).create();
        }
        //不存在也创建
        boolean b = restTemplate.indexOps(IndexCoordinates.of("sys_user")).create();
        return b;
    }


    @GetMapping("/all")
    public List<Item> findAll() {
        //查询所有
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(QueryBuilders.matchAllQuery()).build();
        SearchHits<Item> searchHits = restTemplate.search(searchQuery, Item.class);
        Stream<SearchHit<Item>> hitStream = searchHits.get();
        List<Item> itemList = hitStream.map(SearchHit::getContent).collect(Collectors.toList());
        return itemList;
    }
}
